<?php
/**
 * @author 逍遥·李志亮 <xiaoyao.working@gmail.com>
 */
function asset($path) {
	$filename = DOC_PATH . ltrim($path, '/');
	$ms       = md5('store' . SYS_VERSION);
	if (file_exists($filename)) {
		$mtime = filemtime($filename);
		$ms    = $mtime ? md5('store' . $mtime) : $ms;
	}
	return ASSETS_DOMAIN . $path . '?ms=' . $ms;
}

function app() {
	global $app;
	return $app;
}

/**
 * @author 逍遥·李志亮 <xiaoyao.working@gmail.com>
 */
function url() {
	$path       = '/';
	$model_name = MODULE_NAME;
	$params     = [];
	$numargs    = func_num_args();
	$args       = func_get_args();
	switch ($numargs) {
	case 0:
		break;
	case 1:
		$path = $args[0];
		break;
	case 2:
		$path = $args[0];
		if (is_array($args[1])) {
			$params = $args[1];
		} else {
			$model_name = ucfirst(strtolower($args[1]));
		}
		break;
	case 3:
	default:
		$path       = $args[0];
		$model_name = $args[1];
		$params     = $args[2];
		break;
	}
	if (C('APP_SUB_DOMAIN_DEPLOY')) {
		$domains = C('APP_SUB_DOMAIN_RULES');
		$domains = array_flip($domains);
		if (isset($domains[$model_name])) {
			if (preg_match('/\{(.*)\}/', $domains[$model_name], $match)) {
				$current_site         = get_site_info(get_siteid());
				$domains[$model_name] = str_replace('{' . $match[1] . '}', $current_site['dirname'], $domains[$model_name]);
			}
		}
		$base_url = isset($domains[$model_name]) ? 'http://' . $domains[$model_name] . '/' : '/';
	}
	$path = str_replace('.html', '', $path);
	return '/' === $path ? $base_url : $base_url . trim($path, '/') . '.html' . (empty($params) ? '' : '?' . http_build_query($params));
}

/**
 * @author 逍遥·李志亮 <xiaoyao.working@gmail.com>
 */
if (!function_exists('http_response_code')) {
	function http_response_code($code = null) {
		if (null !== $code) {
			switch ($code) {
			case 100:$text = 'Continue';
				break;
			case 101:$text = 'Switching Protocols';
				break;
			case 200:$text = 'OK';
				break;
			case 201:$text = 'Created';
				break;
			case 202:$text = 'Accepted';
				break;
			case 203:$text = 'Non-Authoritative Information';
				break;
			case 204:$text = 'No Content';
				break;
			case 205:$text = 'Reset Content';
				break;
			case 206:$text = 'Partial Content';
				break;
			case 300:$text = 'Multiple Choices';
				break;
			case 301:$text = 'Moved Permanently';
				break;
			case 302:$text = 'Moved Temporarily';
				break;
			case 303:$text = 'See Other';
				break;
			case 304:$text = 'Not Modified';
				break;
			case 305:$text = 'Use Proxy';
				break;
			case 400:$text = 'Bad Request';
				break;
			case 401:$text = 'Unauthorized';
				break;
			case 402:$text = 'Payment Required';
				break;
			case 403:$text = 'Forbidden';
				break;
			case 404:$text = 'Not Found';
				break;
			case 405:$text = 'Method Not Allowed';
				break;
			case 406:$text = 'Not Acceptable';
				break;
			case 407:$text = 'Proxy Authentication Required';
				break;
			case 408:$text = 'Request Time-out';
				break;
			case 409:$text = 'Conflict';
				break;
			case 410:$text = 'Gone';
				break;
			case 411:$text = 'Length Required';
				break;
			case 412:$text = 'Precondition Failed';
				break;
			case 413:$text = 'Request Entity Too Large';
				break;
			case 414:$text = 'Request-URI Too Large';
				break;
			case 415:$text = 'Unsupported Media Type';
				break;
			case 500:$text = 'Internal Server Error';
				break;
			case 501:$text = 'Not Implemented';
				break;
			case 502:$text = 'Bad Gateway';
				break;
			case 503:$text = 'Service Unavailable';
				break;
			case 504:$text = 'Gateway Time-out';
				break;
			case 505:$text = 'HTTP Version not supported';
				break;
			default:
				exit('Unknown http status code "' . htmlentities($code) . '"');
				break;
			}
			$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
			header($protocol . ' ' . $code . ' ' . $text);
			$GLOBALS['http_response_code'] = $code;
		} else {
			$code = (isset($GLOBALS['http_response_code']) ? $GLOBALS['http_response_code'] : 200);
		}
		return $code;
	}
}

/**
 * @author 逍遥·李志亮 <xiaoyao.working@gmail.com>
 */
function abort($code = 404, $module_name = '') {
	http_response_code($code);
	if (IS_AJAX) {
		header('Content-Type:application/json; charset=utf-8');
		exit(json_encode(['code' => $code, 'message' => 'system error!']));
	} else {
		$module_name = empty($module_name) ? MODULE_NAME : $module_name;
		$view        = \Think\Think::instance('Think\View');
		switch ($code) {
		case '500':
			$content = $view->display($module_name . '@errors:500');
			break;
		default:
			$content = $view->display($module_name . '@errors:404');
			break;
		}
		exit();
	}
}

/**
 * 创建logic
 * @author 逍遥·李志亮 <xiaoyao.working@gmail.com>
 *
 * @param  string    $name logic名称
 * @return B\Logic
 */
function logic($name, $group = '') {
	$name = parse_name($name, 1);
	if (empty($group)) {
		$group = MODULE_NAME;
	}
	$class = '\\Logic\\' . parse_name($group, 1) . '\\' . $name . 'Logic';
	if (class_exists($class)) {
		$logic = $class::getInstance();
	} else {
		$logic_key = $name;
		$class     = '\\Logic\\' . $name . 'Logic';
		$logic     = class_exists($class) ? $class::getInstance() : \Logic\BaseLogic::getInstance();
	}
	return $logic;
}

/**
 * 创建service
 * @author 逍遥·李志亮 <xiaoyao.working@gmail.com>
 *
 * @param  string                $name service名称
 * @return Service\BaseService
 */
function service($name, $group = '') {
	$name            = parse_name($name, 1);
	static $_service = [];
	if (empty($group)) {
		$group = MODULE_NAME;
	}
	$service_key = $group . $name;
	if (isset($_service[$service_key])) {
		return $_service[$service_key];
	}

	$class = '\\Service\\' . parse_name($group, 1) . '\\' . $name . 'Service';
	if (class_exists($class)) {
		$service = new $class;
	} else {
		$service_key = $name;
		$class       = '\\Service\\' . $name . 'Service';
		$service     = class_exists($class) ? new $class : new \Service\BaseService;
	}
	$_service[$service_key] = $service;
	return $service;

}

/**
 * 创建model
 * @author 逍遥·李志亮 <xiaoyao.working@gmail.com>
 *
 * @param  string                $name service名称
 * @return Service\BaseService
 */
function model($name, $group = '') {
	$name = parse_name($name, 1);
	if (empty($group)) {
		$group = MODULE_NAME;
	}
	$class = '\\Model\\' . parse_name($group, 1) . '\\' . $name . 'Model';
	if (class_exists($class)) {
		$model = $class::getInstance();
	} else {
		$model_key = $name;
		$class     = '\\Model\\' . $name . 'Model';
		$model     = class_exists($class) ? $class::getInstance() : M($name);
	}
	return $model;
}

/**
 * 获取系统配置选项
 * @param string $option_key 系统配置项键
 */
function get_system_option($option_key = '') {
	static $system_options = '';
	if (empty($system_options)) {
		$system_options = F('SysOptions');
		if (!$system_options) {
			$system_options = logic('Options', 'Admin')->setCache();
		}
	}

	if (empty($option_key)) {
		return $system_options;
	} else {
		return isset($system_options[$option_key]) ? $system_options[$option_key] : '';
	}
}

/**
 * 获取系统微博应用账号信息
 */
function get_weiboauth_options() {
	return [
		'app_key'      => get_system_option('wb_app_key'),
		'app_secret'   => get_system_option('wb_app_secret'),
		'app_callback' => get_system_option('wb_app_callback'),
	];
}

/**
 * 获取QQ应用账号信息
 */
function get_qqauth_options() {
	return [
		'app_id'       => get_system_option('qq_app_id'),
		'app_key'      => get_system_option('qq_app_key'),
		'app_callback' => get_system_option('qq_app_callback'),
	];
}

function tree_to_array($tree, &$cat = [], $level = 1) {
	foreach ($tree as $key => $value) {
		$temp = $value;
		if (isset($temp['_child']) && $temp['_child']) {
			$temp['_child'] = true;
			$temp['level']  = $level;
			$cat[]          = $temp;
		} else {
			$temp['_child'] = false;
			$temp['level']  = $level;
			$cat[]          = $temp;
		}
		if (isset($value['_child']) && $value['_child']) {
			tree_to_array($value['_child'], $cat, ($level + 1));
		}
	}
}

/**
 * 获取站点配置信息
 * @param $siteid 站点id
 */
function get_site_setting($siteid) {
	$siteid   = $siteid ? $siteid : 1;
	$siteinfo = get_site_info($siteid);
	return string2array($siteinfo['setting']);
}

function get_site_info($siteid = "") {
	static $sitelist = '';
	if (empty($sitelist)) {
		$sitelist = F('sitelist');
		if (!$sitelist) {
			$sitelist = logic('site', 'Admin')->setCache();
		}
	}
	if (empty($siteid)) {
		return $sitelist;
	} else {
		return $sitelist[$siteid];
	}
}

function get_site_seo_info($siteid = "") {
	$seo                = [];
	$siteid             = $siteid ? $siteid : 1;
	$siteinfo           = get_site_info($siteid);
	$seo['title']       = $siteinfo['site_title'];
	$seo['keywords']    = $siteinfo['keywords'];
	$seo['description'] = $siteinfo['description'];
	return $seo;
}

/**
 * 获取当前的站点ID
 */
function get_siteid() {
	if (defined('IN_ADMIN')) {
		$siteid = session('siteid');
		$siteid = empty($siteid) ? 1 : $siteid;
	} else {
		// 用cookie来判断
		$siteid = cookie('siteid');
		if (empty($siteid)) {
			$current_site = set_site_by_domain();
			$siteid       = $current_site['id'];
		}
	}
	return $siteid;
}

/**
 * 设置站点ID
 * @param string $domain 域名
 */
function set_site_by_domain($domain = '') {
	if (empty($domain)) {
		$domain = $_SERVER['HTTP_HOST'];
	}
	$sites        = get_site_info();
	$current_site = '';
	foreach ($sites as $key => $site) {
		if ($site['domain'] == 'http://' . $domain) {
			$current_site = $site;
			break;
		}
	}
	if (empty($current_site)) {
		$current_site = reset($sites);
	}
	cookie('siteid', $current_site['id'], ['expire' => 86400000, 'domain' => $current_site['base_domain']]);
	return $current_site;
}

/**
 * 设置站点ID
 * @param string $domain 域名
 */
function set_site_by_id($siteid) {
	$site = get_site_info($siteid);
	cookie('siteid', $site['id'], ['expire' => 86400000, 'domain' => $site['base_domain']]);
	return $site;
}

/**
 * 检查id是否存在于数组中
 *
 * @param $id
 * @param $ids
 * @param $s
 */
function check_in($id, $ids = '', $s = ',') {
	if (!$ids) {
		return false;
	}

	$ids = explode($s, $ids);
	return is_array($id) ? array_intersect($id, $ids) : in_array($id, $ids);
}

/**
 * 取得文件扩展
 *
 * @param  $filename   文件名
 * @return 扩展名
 */
function fileext($filename) {
	return strtolower(trim(substr(strrchr($filename, '.'), 1, 10)));
}

/**
 * 转换字节数为其他单位
 *
 * @param  string $filesize      字节大小
 * @return string 返回大小
 */
function sizecount($filesize) {
	if ($filesize >= 1073741824) {
		$filesize = round($filesize / 1073741824 * 100) / 100 . ' GB';
	} elseif ($filesize >= 1048576) {
		$filesize = round($filesize / 1048576 * 100) / 100 . ' MB';
	} elseif ($filesize >= 1024) {
		$filesize = round($filesize / 1024 * 100) / 100 . ' KB';
	} else {
		$filesize = $filesize . ' B';
	}
	return $filesize;
}

function size2int($filesize) {
	$filesize = strtoupper($filesize);
	if (strpos($filesize, 'G')) {
		$filesize = intval($filesize) * 1073741824;
	} elseif (strpos($filesize, 'M')) {
		$filesize = intval($filesize) * 1048576;
	} elseif (strpos($filesize, 'K')) {
		$filesize = intval($filesize) * 1024;
	}
	return $filesize;
}

/**
 * 生成随机字符串
 * @param  int      $length 要生成的随机字符串长度
 * @param  string   $type   随机码类型：0，数字+大写字母；1，数字；2，小写字母；3，大写字母；4，特殊字符；-1，数字+大小写字母+特殊字符
 * @return string
 */
function randCode($length = 5, $type = 0) {
	$arr = [1 => "0123456789", 2 => "abcdefghijklmnopqrstuvwxyz", 3 => "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 4 => "~@#$%^&*(){}[]|"];
	if ($type == 0) {
		array_pop($arr);
		$string = implode("", $arr);
	} else if ($type == "-1") {
		$string = implode("", $arr);
	} else {
		$string = $arr[$type];
	}
	$count = strlen($string) - 1;
	for ($i = 0; $i < $length; $i++) {
		$str[$i] = $string[rand(0, $count)];
		$code .= $str[$i];
	}
	return $code;
}

/**
 * 删除目录及目录下所有文件或删除指定文件
 * @param  str  $path                待删除目录路径
 * @param  int  $delDir              是否删除目录，1或true删除目录，0或false则只删除文件保留目录（包含子目录）
 * @return bool 返回删除状态
 */
function delDirAndFile($path, $delDir = FALSE) {
	$message = "";
	$handle  = opendir($path);
	if ($handle) {
		while (false !== ($item = readdir($handle))) {
			if ($item != "." && $item != "..") {
				if (is_dir("$path/$item")) {
					$msg = delDirAndFile("$path/$item", $delDir);
					if ($msg) {
						$message .= $msg;
					}
				} else {
					$message .= "删除文件" . $item;
					if (unlink("$path/$item")) {
						$message .= "成功<br />";
					} else {
						$message .= "失败<br />";
					}
				}
			}
		}
		closedir($handle);
		if ($delDir) {
			if (rmdir($path)) {
				$message .= "删除目录" . dirname($path) . "<br />";
			} else {
				$message .= "删除目录" . dirname($path) . "失败<br />";
			}

		}
	} else {
		if (file_exists($path)) {
			if (unlink($path)) {
				$message .= "删除文件" . basename($path) . "<br />";
			} else {
				$message .= "删除文件"+basename($path) . "失败<br />";
			}
		} else {
			$message .= "文件"+basename($path) . "不存在<br />";
		}
	}
	return $message;
}

/**
 * 将一个字符串部分字符用*替代隐藏
 * @param  string $string                 待转换的字符串
 * @param  int    $bengin                 起始位置，从0开始计数，当$type=4时，表示左侧保留长度
 * @param  int    $len                    需要转换成*的字符个数，当$type=4时，表示右侧保留长度
 * @param  int    $type                   转换类型：0，从左向右隐藏；1，从右向左隐藏；2，从指定字符位置分割前由右向左隐藏；3，从指定字符位置分割后由左向右隐藏；4，保留首末指定字符串
 * @param  string $glue                   分割符
 * @return string 处理后的字符串
 */
function hideStr($string, $bengin = 0, $len = 4, $type = 0, $glue = "@") {
	if (empty($string)) {
		return false;
	}

	$array = [];
	if ($type == 0 || $type == 1 || $type == 4) {
		$strlen = $length = mb_strlen($string);
		while ($strlen) {
			$array[] = mb_substr($string, 0, 1, "utf8");
			$string  = mb_substr($string, 1, $strlen, "utf8");
			$strlen  = mb_strlen($string);
		}
	}
	switch ($type) {
	case 1:
		$array = array_reverse($array);
		for ($i = $bengin; $i < ($bengin + $len); $i++) {
			if (isset($array[$i])) {
				$array[$i] = "*";
			}

		}
		$string = implode("", array_reverse($array));
		break;
	case 2:
		$array    = explode($glue, $string);
		$array[0] = hideStr($array[0], $bengin, $len, 1);
		$string   = implode($glue, $array);
		break;
	case 3:
		$array    = explode($glue, $string);
		$array[1] = hideStr($array[1], $bengin, $len, 0);
		$string   = implode($glue, $array);
		break;
	case 4:
		$left  = $bengin;
		$right = $len;
		$tem   = [];
		for ($i = 0; $i < ($length - $right); $i++) {
			if (isset($array[$i])) {
				$tem[] = $i >= $left ? "*" : $array[$i];
			}

		}
		$array = array_chunk(array_reverse($array), $right);
		$array = array_reverse($array[0]);
		for ($i = 0; $i < $right; $i++) {
			$tem[] = $array[$i];
		}
		$string = implode("", $tem);
		break;
	default:
		for ($i = $bengin; $i < ($bengin + $len); $i++) {
			if (isset($array[$i])) {
				$array[$i] = "*";
			}

		}
		$string = implode("", $array);
		break;
	}
	return $string;
}

/**
 * 返回经addslashes处理过的字符串或数组
 * @param  $string 需要处理的字符串或数组
 * @return mixed
 */
function new_addslashes($string) {
	if (!is_array($string)) {
		return addslashes($string);
	}

	foreach ($string as $key => $val) {
		$string[$key] = new_addslashes($val);
	}

	return $string;
}

/**
 * 返回经stripslashes处理过的字符串或数组
 * @param  $string 需要处理的字符串或数组
 * @return mixed
 */
function new_stripslashes($string) {
	if (!is_array($string)) {
		return stripslashes($string);
	}

	foreach ($string as $key => $val) {
		$string[$key] = new_stripslashes($val);
	}

	return $string;
}

/**
 * 返回经htmlspecialchars处理过的字符串或数组
 * @param  $obj    需要处理的字符串或数组
 * @return mixed
 */
function new_html_special_chars($string) {
	if (!is_array($string)) {
		return htmlspecialchars($string);
	}

	foreach ($string as $key => $val) {
		$string[$key] = new_html_special_chars($val);
	}

	return $string;
}

/**
 * 将字符串转换为数组
 *
 * @param  string $data                                                           字符串
 * @return array  返回数组格式，如果，data为空，则返回空数组
 */
function string2array($data) {
	if ($data == '' || strpos($data, 'array') !== 0) {
		return [];
	}

	@eval("\$array = $data;");
	return $array;
}
/**
 * 将数组转换为字符串
 *
 * @param  array  $data                                                  数组
 * @param  bool   $isformdata                                            如果为0，则不使用new_stripslashes处理，可选参数，默认为1
 * @return string 返回字符串，如果，data为空，则返回空
 */
function array2string($data, $isformdata = 1) {
	if ($data == '') {
		return '';
	}

	if ($isformdata) {
		$data = new_stripslashes($data);
	}

	return var_export($data, TRUE);
}

/**
 * 安全过滤函数
 *
 * @param  $string
 * @return string
 */
function safe_replace($string) {
	$string = str_replace('%20', '', $string);
	$string = str_replace('%27', '', $string);
	$string = str_replace('%2527', '', $string);
	$string = str_replace('*', '', $string);
	$string = str_replace('"', '&quot;', $string);
	$string = str_replace("'", '', $string);
	$string = str_replace('"', '', $string);
	$string = str_replace(';', '', $string);
	$string = str_replace('<', '&lt;', $string);
	$string = str_replace('>', '&gt;', $string);
	$string = str_replace("{", '', $string);
	$string = str_replace('}', '', $string);
	$string = str_replace('\\', '', $string);
	return $string;
}

/**
 * xss过滤函数
 *
 * @param  $string
 * @return string
 */
function remove_xss($string) {
	$string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S', '', $string);

	$parm1 = ['javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base'];

	$parm2 = ['onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload'];

	$parm = array_merge($parm1, $parm2);

	for ($i = 0; $i < sizeof($parm); $i++) {
		$pattern = '/';
		for ($j = 0; $j < strlen($parm[$i]); $j++) {
			if ($j > 0) {
				$pattern .= '(';
				$pattern .= '(&#[x|X]0([9][a][b]);?)?';
				$pattern .= '|(&#0([9][10][13]);?)?';
				$pattern .= ')?';
			}
			$pattern .= $parm[$i][$j];
		}
		$pattern .= '/i';
		$string = preg_replace($pattern, '', $string);
	}
	return $string;
}

/**
 * 过滤ASCII码从0-28的控制字符
 * @return String
 */
function trim_unsafe_control_chars($str) {
	$rule = '/[' . chr(1) . '-' . chr(8) . chr(11) . '-' . chr(12) . chr(14) . '-' . chr(31) . ']*/';
	return str_replace(chr(0), '', preg_replace($rule, '', $str));
}

/**
 * 格式化文本域内容
 *
 * @param  $string  文本域内容
 * @return string
 */
function trim_textarea($string) {
	$string = nl2br(str_replace(' ', '&nbsp;', $string));
	return $string;
}

/**
 * 将文本格式成适合js输出的字符串
 * @param  string $string                 需要处理的字符串
 * @param  intval $isjs                   是否执行字符串格式化，默认为执行
 * @return string 处理后的字符串
 */
function format_js($string, $isjs = 1) {
	$string = addslashes(str_replace(["\r", "\n", "\t"], ['', '', ''], $string));
	return $isjs ? 'document.write("' . $string . '");' : $string;
}

/**
 * 转义 javascript 代码标记
 *
 * @param  $str
 * @return mixed
 */
function trim_script($str) {
	if (is_array($str)) {
		foreach ($str as $key => $val) {
			$str[$key] = trim_script($val);
		}
	} else {
		$str = preg_replace('/\<([\/]?)script([^\>]*?)\>/si', '&lt;\\1script\\2&gt;', $str);
		$str = preg_replace('/\<([\/]?)iframe([^\>]*?)\>/si', '&lt;\\1iframe\\2&gt;', $str);
		$str = preg_replace('/\<([\/]?)frame([^\>]*?)\>/si', '&lt;\\1frame\\2&gt;', $str);
		$str = str_replace('javascript:', 'javascript：', $str);
	}
	return $str;
}

/**
 * 字符截取 支持UTF8/GBK
 * @param $string
 * @param $length
 * @param $dot
 */
function str_cut($string, $length, $dot = '...') {
	$strlen = strlen($string);
	if ($strlen <= $length) {
		return $string;
	}

	$string = str_replace([' ', '&nbsp;', '&amp;', '&quot;', '&#039;', '&ldquo;', '&rdquo;', '&mdash;', '&lt;', '&gt;', '&middot;', '&hellip;'], ['∵', ' ', '&', '"', "'", '“', '”', '—', '<', '>', '·', '…'], $string);
	$strcut = '';
	if (strtolower(CHARSET) == 'utf-8') {
		$length = intval($length - strlen($dot) - $length / 3);
		$n      = $tn      = $noc      = 0;
		while ($n < strlen($string)) {
			$t = ord($string[$n]);
			if ($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
				$tn = 1;
				$n++;
				$noc++;
			} elseif (194 <= $t && $t <= 223) {
				$tn = 2;
				$n += 2;
				$noc += 2;
			} elseif (224 <= $t && $t <= 239) {
				$tn = 3;
				$n += 3;
				$noc += 2;
			} elseif (240 <= $t && $t <= 247) {
				$tn = 4;
				$n += 4;
				$noc += 2;
			} elseif (248 <= $t && $t <= 251) {
				$tn = 5;
				$n += 5;
				$noc += 2;
			} elseif ($t == 252 || $t == 253) {
				$tn = 6;
				$n += 6;
				$noc += 2;
			} else {
				$n++;
			}
			if ($noc >= $length) {
				break;
			}
		}
		if ($noc > $length) {
			$n -= $tn;
		}
		$strcut = substr($string, 0, $n);
		$strcut = str_replace(['∵', '&', '"', "'", '“', '”', '—', '<', '>', '·', '…'], [' ', '&amp;', '&quot;', '&#039;', '&ldquo;', '&rdquo;', '&mdash;', '&lt;', '&gt;', '&middot;', '&hellip;'], $strcut);
	} else {
		$dotlen      = strlen($dot);
		$maxi        = $length - $dotlen - 1;
		$current_str = '';
		$search_arr  = ['&', ' ', '"', "'", '“', '”', '—', '<', '>', '·', '…', '∵'];
		$replace_arr = ['&amp;', '&nbsp;', '&quot;', '&#039;', '&ldquo;', '&rdquo;', '&mdash;', '&lt;', '&gt;', '&middot;', '&hellip;', ' '];
		$search_flip = array_flip($search_arr);
		for ($i = 0; $i < $maxi; $i++) {
			$current_str = ord($string[$i]) > 127 ? $string[$i] . $string[++$i] : $string[$i];
			if (in_array($current_str, $search_arr)) {
				$key         = $search_flip[$current_str];
				$current_str = str_replace($search_arr[$key], $replace_arr[$key], $current_str);
			}
			$strcut .= $current_str;
		}
	}
	return $strcut . $dot;
}

/**
 * 检测输入中是否含有错误字符
 *
 * @param  char $string 要检查的字符串名称
 * @return TRUE or FALSE
 */
function is_badword($string) {
	$badwords = ["\\", '&', ' ', "'", '"', '/', '*', ',', '<', '>', "\r", "\t", "\n", "#"];
	foreach ($badwords as $value) {
		if (strpos($string, $value) !== FALSE) {
			return TRUE;
		}
	}
	return FALSE;
}

/**
 * 功能：检测一个目录是否存在，不存在则创建它
 * @param  string    $path 待检测的目录
 * @return boolean
 */
function makeDir($path) {
	return is_dir($path) or (makeDir(dirname($path)) and @mkdir($path, 0777));
}

/**
 * 功能：检测一个字符串是否是邮件地址格式
 * @param  string    $value 待检测字符串
 * @return boolean
 */
function is_email($value) {
	return preg_match("/^[0-9a-zA-Z]+(?:[\_\.\-][a-z0-9\-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\.[a-zA-Z]+$/i", $value);
}

// /**
// * 邮件发送
// * @param $tomail 收件人
// * @param $subjtct 标题
// * @param $content 内容
// */

// function sendEmail($tomail,$subject,$content) {
//     require EMAIL_PATH . 'PHPMailerAutoload.php';
//     $mail = new \PHPMailer;
//     $mail ->CharSet = 'UTF-8';
//     $mail ->isSMTP();
//     $mail ->Host = C('EMAIL_CONF')['MAIL_HOST'];
//     $mail ->SMTPAuth = true;
//     $mail ->Username = C('EMAIL_CONF')['MAIL_USER'];
//     $mail ->Password = C('EMAIL_CONF')['MAIL_PASS'];
//     $mail ->SMTPSecure ='ssl';
//     $mail ->Port = C('EMAIL_CONF')['MAIL_PORT'];
//     $mail ->FromName = C('EMAIL_CONF')['MAIL_TITLE'];
//     $mail ->setFrom($mail->Username,$mail->FromName);
//     $mail ->addAddress($tomail);
//     $mail ->isHTML(true);
//     $mail ->Subject = $subject;

//     $mail ->Body = '<div style="paddiing:80px;font-size:20px;">亲爱的<b>' . $mail->FromName . '</b>用户，你好！</div><p>你的验证码是：<span style="color:blue;">' .$content . '</span></p><p>此邮件由系统自动发出，请勿直接回复。</p>';
//     $code = session('mail_code',$content);
//     if(!$mail->send()) {
//         return false;
//     }
//     return session('mail_code');
// }

/**
 * 文件下载
 * @param $filepath 文件路径
 * @param $filename 文件名称
 */
function file_down($filepath, $filename = '') {
	if (!$filename) {
		$filename = basename($filepath);
	}

	if (is_ie()) {
		$filename = rawurlencode($filename);
	}

	$filetype = fileext($filename);
	$filesize = sprintf("%u", filesize($filepath));
	if (ob_get_length() !== false) {
		@ob_end_clean();
	}

	header('Pragma: public');
	header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
	header('Cache-Control: no-store, no-cache, must-revalidate');
	header('Cache-Control: pre-check=0, post-check=0, max-age=0');
	header('Content-Transfer-Encoding: binary');
	header('Content-Encoding: none');
	header('Content-type: ' . $filetype);
	header('Content-Disposition: attachment; filename="' . $filename . '"');
	header('Content-length: ' . $filesize);
	readfile($filepath);
	exit;
}

/**
 * 检查GD库是否支持
 */
function check_gd() {
	if (!function_exists('imagepng') && !function_exists('imagejpeg') && !function_exists('imagegif')) {
		$gd = L('gd_unsupport');
	} else {
		$gd = L('gd_support');
	}
	return $gd;
}

/**
 * 按照尺寸生成缩略图
 * @param $image  原图片地址
 * @param $width  缩略图宽度
 * @param $height 缩略图高度
 */
function thumb($imgurl, $width = 100, $height = 100, $type = 3, $smallpic = 'nopic.jpg') {
	if (empty($imgurl)) {
		return ASSETS_DOMAIN . "images/home/" . $smallpic;
	}
	$imgurl_replace = str_replace(IMAGE_DOMAIN, '', $imgurl);
	if (!extension_loaded('gd') || strpos($imgurl_replace, '://')) {
		return $imgurl_replace;
	}
	$thumbs = logic('attachment', 'Admin')->thumb($imgurl_replace, $width, $height, $type);
	return ($thumbs === false) ? $imgurl : IMAGE_DOMAIN . current($thumbs);
}

function image_full_url($imgurl) {
	return strpos($imgurl, '://') ? $imgurl : IMAGE_DOMAIN . $imgurl;
}

function check_image_thumb($image) {
	return extension_loaded('gd') && preg_match("/\.(jpg|jpeg|gif|png)/i", $image, $m) && file_exists($image) && function_exists('imagecreatefrom' . ($m[1] == 'jpg' ? 'jpeg' : $m[1]));
}

function get_location($ip_address) {
	static $ip;
	if (empty($ip)) {
		$ip = new \Org\Net\IpLocation(); // 实例化类 参数表示IP地址库文件
	}
	$iplocation = $ip->getlocation($ip_address); // 获取某个IP地址所在的位置
	$area       = gbk_to_utf8($iplocation['country'] . $iplocation['area']);
	return $area;
}

function get_taobao_location($ip_address) {
	$ip_info = @file_get_contents('http://ip.taobao.com/service/getIpInfo.php?ip=' . $ip_address);
	if (empty($ip_info)) {
		return "未知";
	}
	$ip_arr = json_decode($ip_info, true);
	if ($ip_arr['code'] == 0) {
		return $ip_arr['data']['region'] . '-' . $ip_arr['data']['city'];
	}
	return "未知";
}

/**
 * 提示信息页面跳转，跳转地址如果传入数组，页面会提示多个地址供用户选择，默认跳转地址为数组的第一个值，时间为5秒。
 * showmessage('登录成功', array('默认跳转地址'=>'http://www.hhailuo.com'));
 * @param string              $message     提示信息
 * @param mixed(string/array) $url_forward 跳转地址
 * @param int                 $ms          跳转等待时间
 */
function showmessage($message, $jumpUrl = '', $waitSecond = 3, $dialog = '', $returnjs = '') {
	if (empty($jumpUrl)) {
		$jumpUrl = $_SERVER['HTTP_REFERER'];
	}
	$theme = C('DEFAULT_THEME');
	if (defined('IN_ADMIN')) {
		include MODULE_PATH . 'View' . (empty($theme) ? '' : DS . $theme) . DS . "Public" . DS . "showMessage.html";
	} else {
		include MODULE_PATH . 'View' . (empty($theme) ? '' : DS . $theme) . DS . "Public" . DS . "error.html";
	}
	exit;
}

/**
 * 当前路径
 * 返回指定栏目路径层级
 * @param $catid  栏目id
 * @param $symbol 栏目间隔符
 */
function catpos($catid, $symbol = ' > ', $category_arr) {
	$sites  = include COMMON_PATH . "Cache/sitelist.php";
	$siteid = get_siteid();
	if (!isset($category_arr[$catid])) {
		return '';
	}

	$pos         = '';
	$siteurl     = str_replace('http://', '', $sites[$category_arr[$catid]['siteid']]['domain']);
	$arrparentid = array_filter(explode(',', $category_arr[$catid]['arrparentid'] . ',' . $catid));
	$pos         = '<ol class="breadcrumb">';
	foreach ($arrparentid as $catid) {
		$url = U(MODULE_NAME . '/Content/lists@' . $siteurl, 'catid=' . $catid);
		$pos .= '<li><a href="' . $url . '">' . $category_arr[$catid]['catname'] . $symbol . '</a></li>';
	}
	$pos .= '</ol>';
	return $pos;
}

/**
 *  将数组转换成以主键值为key的多维数组
 * @param array  $array 需要转换的数组
 * @param string $_key  主键名称
 */

function array_key_translate($array, $_key = 'id') {
	if (is_array($array)) {
		$temp = [];
		foreach ($array as $value) {
			$temp[$value[$_key]] = $value;
		}
		return $temp;
	}
	return $array;
}

/**
 *  将数组转换成 主键 => 值 的键值对(一维数组)，适应select
 * @param array  $array  需要转换的数组
 * @param string $_key   主键名称
 * @param string $_value 字段名称
 */

function array_translate($array, $_key = 'id', $_value = 'name') {
	if (is_array($array)) {
		$temp = [];
		foreach ($array as $value) {
			$temp[$value[$_key]] = $value[$_value];
		}
		return $temp;
	}
	return $array;
}

/**
 * 字符串截取，支持中文和其他编码
 * @static
 * @access public
 * @param  string   $str     需要转换的字符串
 * @param  string   $start   开始位置
 * @param  string   $length  截取长度
 * @param  string   $charset 编码格式
 * @param  string   $suffix  截断显示字符
 * @return string
 */
function msubstr($str, $start = 0, $length, $charset = "utf-8", $suffix = true) {
	if (empty($str)) {
		return $str;
	}
	if (function_exists("mb_substr")) {
		$slice = mb_substr($str, $start, $length, $charset);
	} elseif (function_exists('iconv_substr')) {
		$slice = iconv_substr($str, $start, $length, $charset);
		if (false === $slice) {
			$slice = '';
		}
	} else {
		$re['utf-8']  = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
		$re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
		$re['gbk']    = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
		$re['big5']   = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
		preg_match_all($re[$charset], $str, $match);
		$slice = join("", array_slice($match[0], $start, $length));
	}
	return $suffix ? $slice . ((mb_strlen($str) > ($start + $length)) ? '...' : '') : $slice;
}

/**
 * 产生随机字串，可用来自动生成密码 默认长度6位 字母和数字混合
 * 0 字母 1 数字 其它 混合
 * @param  string   $len      长度
 * @param  string   $type     字串类型
 * @param  string   $addChars 额外字符
 * @return string
 */
function rand_string($len = 6, $type = '', $addChars = '') {
	$str = '';
	switch ($type) {
	case 0:
		$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' . $addChars;
		break;
	case 1:
		$chars = str_repeat('0123456789', 3);
		break;
	case 2:
		$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' . $addChars;
		break;
	case 3:
		$chars = 'abcdefghijklmnopqrstuvwxyz' . $addChars;
		break;
	case 4:
		$chars = "们以我到他会作时要动国产的一是工就年阶义发成部民可出能方进在了不和有大这主中人上为来分生对于学下级地个用同行面说种过命度革而多子后自社加小机也经力线本电高量长党得实家定深法表着水理化争现所二起政三好十战无农使性前等反体合斗路图把结第里正新开论之物从当两些还天资事队批点育重其思与间内去因件日利相由压员气业代全组数果期导平各基或月毛然如应形想制心样干都向变关问比展那它最及外没看治提五解系林者米群头意只明四道马认次文通但条较克又公孔领军流入接席位情运器并飞原油放立题质指建区验活众很教决特此常石强极土少已根共直团统式转别造切九你取西持总料连任志观调七么山程百报更见必真保热委手改管处己将修支识病象几先老光专什六型具示复安带每东增则完风回南广劳轮科北打积车计给节做务被整联步类集号列温装即毫知轴研单色坚据速防史拉世设达尔场织历花受求传口断况采精金界品判参层止边清至万确究书术状厂须离再目海交权且儿青才证低越际八试规斯近注办布门铁需走议县兵固除般引齿千胜细影济白格效置推空配刀叶率述今选养德话查差半敌始片施响收华觉备名红续均药标记难存测士身紧液派准斤角降维板许破述技消底床田势端感往神便贺村构照容非搞亚磨族火段算适讲按值美态黄易彪服早班麦削信排台声该击素张密害侯草何树肥继右属市严径螺检左页抗苏显苦英快称坏移约巴材省黑武培著河帝仅针怎植京助升王眼她抓含苗副杂普谈围食射源例致酸旧却充足短划剂宣环落首尺波承粉践府鱼随考刻靠够满夫失包住促枝局菌杆周护岩师举曲春元超负砂封换太模贫减阳扬江析亩木言球朝医校古呢稻宋听唯输滑站另卫字鼓刚写刘微略范供阿块某功套友限项余倒卷创律雨让骨远帮初皮播优占死毒圈伟季训控激找叫云互跟裂粮粒母练塞钢顶策双留误础吸阻故寸盾晚丝女散焊功株亲院冷彻弹错散商视艺灭版烈零室轻血倍缺厘泵察绝富城冲喷壤简否柱李望盘磁雄似困巩益洲脱投送奴侧润盖挥距触星松送获兴独官混纪依未突架宽冬章湿偏纹吃执阀矿寨责熟稳夺硬价努翻奇甲预职评读背协损棉侵灰虽矛厚罗泥辟告卵箱掌氧恩爱停曾溶营终纲孟钱待尽俄缩沙退陈讨奋械载胞幼哪剥迫旋征槽倒握担仍呀鲜吧卡粗介钻逐弱脚怕盐末阴丰雾冠丙街莱贝辐肠付吉渗瑞惊顿挤秒悬姆烂森糖圣凹陶词迟蚕亿矩康遵牧遭幅园腔订香肉弟屋敏恢忘编印蜂急拿扩伤飞露核缘游振操央伍域甚迅辉异序免纸夜乡久隶缸夹念兰映沟乙吗儒杀汽磷艰晶插埃燃欢铁补咱芽永瓦倾阵碳演威附牙芽永瓦斜灌欧献顺猪洋腐请透司危括脉宜笑若尾束壮暴企菜穗楚汉愈绿拖牛份染既秋遍锻玉夏疗尖殖井费州访吹荣铜沿替滚客召旱悟刺脑措贯藏敢令隙炉壳硫煤迎铸粘探临薄旬善福纵择礼愿伏残雷延烟句纯渐耕跑泽慢栽鲁赤繁境潮横掉锥希池败船假亮谓托伙哲怀割摆贡呈劲财仪沉炼麻罪祖息车穿货销齐鼠抽画饲龙库守筑房歌寒喜哥洗蚀废纳腹乎录镜妇恶脂庄擦险赞钟摇典柄辩竹谷卖乱虚桥奥伯赶垂途额壁网截野遗静谋弄挂课镇妄盛耐援扎虑键归符庆聚绕摩忙舞遇索顾胶羊湖钉仁音迹碎伸灯避泛亡答勇频皇柳哈揭甘诺概宪浓岛袭谁洪谢炮浇斑讯懂灵蛋闭孩释乳巨徒私银伊景坦累匀霉杜乐勒隔弯绩招绍胡呼痛峰零柴簧午跳居尚丁秦稍追梁折耗碱殊岗挖氏刃剧堆赫荷胸衡勤膜篇登驻案刊秧缓凸役剪川雪链渔啦脸户洛孢勃盟买杨宗焦赛旗滤硅炭股坐蒸凝竟陷枪黎救冒暗洞犯筒您宋弧爆谬涂味津臂障褐陆啊健尊豆拔莫抵桑坡缝警挑污冰柬嘴啥饭塑寄赵喊垫丹渡耳刨虎笔稀昆浪萨茶滴浅拥穴覆伦娘吨浸袖珠雌妈紫戏塔锤震岁貌洁剖牢锋疑霸闪埔猛诉刷狠忽灾闹乔唐漏闻沈熔氯荒茎男凡抢像浆旁玻亦忠唱蒙予纷捕锁尤乘乌智淡允叛畜俘摸锈扫毕璃宝芯爷鉴秘净蒋钙肩腾枯抛轨堂拌爸循诱祝励肯酒绳穷塘燥泡袋朗喂铝软渠颗惯贸粪综墙趋彼届墨碍启逆卸航衣孙龄岭骗休借" . $addChars;
		break;
	default:
		// 默认去掉了容易混淆的字符oOLl和数字01，要添加请使用addChars参数
		$chars = 'ABCDEFGHIJKMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789' . $addChars;
		break;
	}
	if ($len > 10) {
		//位数过长重复字符串一定次数
		$chars = $type == 1 ? str_repeat($chars, $len) : str_repeat($chars, 5);
	}
	if ($type != 4) {
		$chars = str_shuffle($chars);
		$str   = substr($chars, 0, $len);
	} else {
		// 中文随机字
		for ($i = 0; $i < $len; $i++) {
			$str .= msubstr($chars, floor(mt_rand(0, mb_strlen($chars, 'utf-8') - 1)), 1);
		}
	}
	return $str;
}

/**
 * 获取登录验证码 默认为4位数字
 * @param  string   $fmode 文件名
 * @return string
 */
function build_verify($length = 4, $mode = 1) {
	return rand_string($length, $mode);
}

/**
 * 字节格式化 把字节数格式为 B K M G T 描述的大小
 * @return string
 */
function byte_format($size, $dec = 2) {
	$a   = ["B", "KB", "MB", "GB", "TB", "PB"];
	$pos = 0;
	while ($size >= 1024) {
		$size /= 1024;
		$pos++;
	}
	return round($size, $dec) . " " . $a[$pos];
}

/**
 * 检查字符串是否是UTF8编码
 * @param  string    $string 字符串
 * @return Boolean
 */
function is_utf8($string) {
	return preg_match('%^(?:
       [\x09\x0A\x0D\x20-\x7E]            # ASCII
       | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
       |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
       | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
       |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
       |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
       | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
       |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
       )*$%xs', $string);
}
/**
 * 代码加亮
 * @param  String   $str  要高亮显示的字符串 或者 文件名
 * @param  Boolean  $show 是否输出
 * @return String
 */
function highlight_code($str, $show = false) {
	if (file_exists($str)) {
		$str = file_get_contents($str);
	}
	$str = stripslashes(trim($str));
	// The highlight string function encodes and highlights
	// brackets so we need them to start raw
	$str = str_replace(['&lt;', '&gt;'], ['<', '>'], $str);

	// Replace any existing PHP tags to temporary markers so they don't accidentally
	// break the string out of PHP, and thus, thwart the highlighting.

	$str = str_replace(['&lt;?php', '?&gt;', '\\'], ['phptagopen', 'phptagclose', 'backslashtmp'], $str);

	// The highlight_string function requires that the text be surrounded
	// by PHP tags.  Since we don't know if A) the submitted text has PHP tags,
	// or B) whether the PHP tags enclose the entire string, we will add our
	// own PHP tags around the string along with some markers to make replacement easier later

	$str = '<?php //tempstart' . "\n" . $str . '//tempend ?>'; // <?

	// All the magic happens here, baby!
	$str = highlight_string($str, TRUE);

	// Prior to PHP 5, the highlight function used icky font tags
	// so we'll replace them with span tags.
	if (abs(phpversion()) < 5) {
		$str = str_replace(['<font ', '</font>'], ['<span ', '</span>'], $str);
		$str = preg_replace('#color="(.*?)"#', 'style="color: \\1"', $str);
	}

	// Remove our artificially added PHP
	$str = preg_replace("#\<code\>.+?//tempstart\<br />\</span\>#is", "<code>\n", $str);
	$str = preg_replace("#\<code\>.+?//tempstart\<br />#is", "<code>\n", $str);
	$str = preg_replace("#//tempend.+#is", "</span>\n</code>", $str);

	// Replace our markers back to PHP tags.
	$str    = str_replace(['phptagopen', 'phptagclose', 'backslashtmp'], ['&lt;?php', '?&gt;', '\\'], $str); //<?
	$line   = explode("<br />", rtrim(ltrim($str, '<code>'), '</code>'));
	$result = '<div class="code"><ol>';
	foreach ($line as $key => $val) {
		$result .= '<li>' . $val . '</li>';
	}
	$result .= '</ol></div>';
	$result = str_replace("\n", "", $result);
	if ($show !== false) {
		echo ($result);
	} else {
		return $result;
	}
}

//输出安全的html
function h($text, $tags = null) {
	$text = trim($text);
	//完全过滤注释
	$text = preg_replace('/<!--?.*-->/', '', $text);
	//完全过滤动态代码
	$text = preg_replace('/<\?|\?' . '>/', '', $text);
	//完全过滤js
	$text = preg_replace('/<script?.*\/script>/', '', $text);

	$text = str_replace('[', '&#091;', $text);
	$text = str_replace(']', '&#093;', $text);
	$text = str_replace('|', '&#124;', $text);
	//过滤换行符
	$text = preg_replace('/\r?\n/', '', $text);
	//br
	$text = preg_replace('/<br(\s\/)?' . '>/i', '[br]', $text);
	$text = preg_replace('/<p(\s\/)?' . '>/i', '[br]', $text);
	$text = preg_replace('/(\[br\]\s*){10,}/i', '[br]', $text);
	//过滤危险的属性，如：过滤on事件lang js
	while (preg_match('/(<[^><]+)( lang|on|action|background|codebase|dynsrc|lowsrc)[^><]+/i', $text, $mat)) {
		$text = str_replace($mat[0], $mat[1], $text);
	}
	while (preg_match('/(<[^><]+)(window\.|javascript:|js:|about:|file:|document\.|vbs:|cookie)([^><]*)/i', $text, $mat)) {
		$text = str_replace($mat[0], $mat[1] . $mat[3], $text);
	}
	if (empty($tags)) {
		$tags = 'table|td|th|tr|i|b|u|strong|img|p|br|div|strong|em|ul|ol|li|dl|dd|dt|a';
	}
	//允许的HTML标签
	$text = preg_replace('/<(' . $tags . ')( [^><\[\]]*)>/i', '[\1\2]', $text);
	$text = preg_replace('/<\/(' . $tags . ')>/Ui', '[/\1]', $text);
	//过滤多余html
	$text = preg_replace('/<\/?(html|head|meta|link|base|basefont|body|bgsound|title|style|script|form|iframe|frame|frameset|applet|id|ilayer|layer|name|script|style|xml)[^><]*>/i', '', $text);
	//过滤合法的html标签
	while (preg_match('/<([a-z]+)[^><\[\]]*>[^><]*<\/\1>/i', $text, $mat)) {
		$text = str_replace($mat[0], str_replace('>', ']', str_replace('<', '[', $mat[0])), $text);
	}
	//转换引号
	while (preg_match('/(\[[^\[\]]*=\s*)(\"|\')([^\2=\[\]]+)\2([^\[\]]*\])/i', $text, $mat)) {
		$text = str_replace($mat[0], $mat[1] . '|' . $mat[3] . '|' . $mat[4], $text);
	}
	//过滤错误的单个引号
	while (preg_match('/\[[^\[\]]*(\"|\')[^\[\]]*\]/i', $text, $mat)) {
		$text = str_replace($mat[0], str_replace($mat[1], '', $mat[0]), $text);
	}
	//转换其它所有不合法的 < >
	$text = str_replace('<', '&lt;', $text);
	$text = str_replace('>', '&gt;', $text);
	$text = str_replace('"', '&quot;', $text);
	//反转换
	$text = str_replace('[', '<', $text);
	$text = str_replace(']', '>', $text);
	$text = str_replace('|', '"', $text);
	//过滤多余空格
	$text = str_replace('  ', ' ', $text);
	return $text;
}

function ubb($Text) {
	$Text = trim($Text);
	//$Text=htmlspecialchars($Text);
	$Text = preg_replace("/\\t/is", "  ", $Text);
	$Text = preg_replace("/\[h1\](.+?)\[\/h1\]/is", "<h1>\\1</h1>", $Text);
	$Text = preg_replace("/\[h2\](.+?)\[\/h2\]/is", "<h2>\\1</h2>", $Text);
	$Text = preg_replace("/\[h3\](.+?)\[\/h3\]/is", "<h3>\\1</h3>", $Text);
	$Text = preg_replace("/\[h4\](.+?)\[\/h4\]/is", "<h4>\\1</h4>", $Text);
	$Text = preg_replace("/\[h5\](.+?)\[\/h5\]/is", "<h5>\\1</h5>", $Text);
	$Text = preg_replace("/\[h6\](.+?)\[\/h6\]/is", "<h6>\\1</h6>", $Text);
	$Text = preg_replace("/\[separator\]/is", "", $Text);
	$Text = preg_replace("/\[center\](.+?)\[\/center\]/is", "<center>\\1</center>", $Text);
	$Text = preg_replace("/\[url=http:\/\/([^\[]*)\](.+?)\[\/url\]/is", "<a href=\"http://\\1\" target=_blank>\\2</a>", $Text);
	$Text = preg_replace("/\[url=([^\[]*)\](.+?)\[\/url\]/is", "<a href=\"http://\\1\" target=_blank>\\2</a>", $Text);
	$Text = preg_replace("/\[url\]http:\/\/([^\[]*)\[\/url\]/is", "<a href=\"http://\\1\" target=_blank>\\1</a>", $Text);
	$Text = preg_replace("/\[url\]([^\[]*)\[\/url\]/is", "<a href=\"\\1\" target=_blank>\\1</a>", $Text);
	$Text = preg_replace("/\[img\](.+?)\[\/img\]/is", "<img src=\\1>", $Text);
	$Text = preg_replace("/\[color=(.+?)\](.+?)\[\/color\]/is", "<font color=\\1>\\2</font>", $Text);
	$Text = preg_replace("/\[size=(.+?)\](.+?)\[\/size\]/is", "<font size=\\1>\\2</font>", $Text);
	$Text = preg_replace("/\[sup\](.+?)\[\/sup\]/is", "<sup>\\1</sup>", $Text);
	$Text = preg_replace("/\[sub\](.+?)\[\/sub\]/is", "<sub>\\1</sub>", $Text);
	$Text = preg_replace("/\[pre\](.+?)\[\/pre\]/is", "<pre>\\1</pre>", $Text);
	$Text = preg_replace("/\[email\](.+?)\[\/email\]/is", "<a href='mailto:\\1'>\\1</a>", $Text);
	$Text = preg_replace("/\[colorTxt\](.+?)\[\/colorTxt\]/eis", "color_txt('\\1')", $Text);
	$Text = preg_replace("/\[emot\](.+?)\[\/emot\]/eis", "emot('\\1')", $Text);
	$Text = preg_replace("/\[i\](.+?)\[\/i\]/is", "<i>\\1</i>", $Text);
	$Text = preg_replace("/\[u\](.+?)\[\/u\]/is", "<u>\\1</u>", $Text);
	$Text = preg_replace("/\[b\](.+?)\[\/b\]/is", "<b>\\1</b>", $Text);
	$Text = preg_replace("/\[quote\](.+?)\[\/quote\]/is", " <div class='quote'><h5>引用:</h5><blockquote>\\1</blockquote></div>", $Text);
	$Text = preg_replace("/\[code\](.+?)\[\/code\]/eis", "highlight_code('\\1')", $Text);
	$Text = preg_replace("/\[php\](.+?)\[\/php\]/eis", "highlight_code('\\1')", $Text);
	$Text = preg_replace("/\[sig\](.+?)\[\/sig\]/is", "<div class='sign'>\\1</div>", $Text);
	$Text = preg_replace("/\\n/is", "<br/>", $Text);
	return $Text;
}

// 随机生成一组字符串
function build_count_rand($number, $length = 4, $mode = 1) {
	if ($mode == 1 && $length < strlen($number)) {
		//不足以生成一定数量的不重复数字
		return false;
	}
	$rand = [];
	for ($i = 0; $i < $number; $i++) {
		$rand[] = rand_string($length, $mode);
	}
	$unqiue = array_unique($rand);
	if (count($unqiue) == count($rand)) {
		return $rand;
	}
	$count = count($rand) - count($unqiue);
	for ($i = 0; $i < $count * 3; $i++) {
		$rand[] = rand_string($length, $mode);
	}
	$rand = array_slice(array_unique($rand), 0, $number);
	return $rand;
}

/**
 * 把返回的数据集转换成Tree
 * @access public
 * @param  array   $list  要转换的数据集
 * @param  string  $pid   parent标记字段
 * @param  string  $level level标记字段
 * @return array
 */
function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = '_child', $root = 0) {
	// 创建Tree
	$tree = [];
	if (is_array($list)) {
		// 创建基于主键的数组引用
		$refer = [];
		foreach ($list as $key => $data) {
			$refer[$data[$pk]] = &$list[$key];
		}
		foreach ($list as $key => $data) {
			// 判断是否存在parent
			$parentId = $data[$pid];
			if ($root == $parentId) {
				$tree[$data[$pk]] = &$list[$key];
			} else {
				if (isset($refer[$parentId])) {
					$parent                     = &$refer[$parentId];
					$parent[$child][$data[$pk]] = &$list[$key];
				}
			}
		}
	}
	return $tree;
}

/**
 * 对查询结果集进行排序
 * @access public
 * asc正向排序 desc逆向排序 nat自然排序
 * @param  array   $list   查询结果
 * @param  string  $field  排序的字段名
 * @param  array   $sortby 排序类型
 * @return array
 */
function list_sort_by($list, $field, $sortby = 'asc') {
	if (is_array($list)) {
		$refer = $resultSet = [];
		foreach ($list as $i => $data) {
			$refer[$i] = &$data[$field];
		}

		switch ($sortby) {
		case 'asc': // 正向排序
			asort($refer);
			break;
		case 'desc': // 逆向排序
			arsort($refer);
			break;
		case 'nat': // 自然排序
			natcasesort($refer);
			break;
		}
		foreach ($refer as $key => $val) {
			$resultSet[] = &$list[$key];
		}

		return $resultSet;
	}
	return false;
}

/**
 * 在数据列表中搜索
 * @access public
 * 支持 array('name'=>$value) 或者 name=$value
 * @param  array   $list      数据列表
 * @param  mixed   $condition 查询条件
 * @return array
 */
function list_search($list, $condition) {
	if (is_string($condition)) {
		parse_str($condition, $condition);
	}

	// 返回的结果集合
	$resultSet = [];
	foreach ($list as $key => $data) {
		$find = false;
		foreach ($condition as $field => $value) {
			if (isset($data[$field])) {
				if (0 === strpos($value, '/')) {
					$find = preg_match($value, $data[$field]);
				} elseif ($data[$field] == $value) {
					$find = true;
				}
			}
		}
		if ($find) {
			$resultSet[] = &$list[$key];
		}

	}
	return $resultSet;
}

// 自动转换字符集 支持数组转换
function auto_charset($fContents, $from = 'gbk', $to = 'utf-8') {
	$from = strtoupper($from) == 'UTF8' ? 'utf-8' : $from;
	$to   = strtoupper($to) == 'UTF8' ? 'utf-8' : $to;
	if (strtoupper($from) === strtoupper($to) || empty($fContents) || (is_scalar($fContents) && !is_string($fContents))) {
		//如果编码相同或者非字符串标量则不转换
		return $fContents;
	}
	if (is_string($fContents)) {
		if (function_exists('mb_convert_encoding')) {
			return mb_convert_encoding($fContents, $to, $from);
		} elseif (function_exists('iconv')) {
			return iconv($from, $to, $fContents);
		} else {
			return $fContents;
		}
	} elseif (is_array($fContents)) {
		foreach ($fContents as $key => $val) {
			$_key             = auto_charset($key, $from, $to);
			$fContents[$_key] = auto_charset($val, $from, $to);
			if ($key != $_key) {
				unset($fContents[$key]);
			}

		}
		return $fContents;
	} else {
		return $fContents;
	}
}

/**
 * 调用关联菜单
 * @param $linkageid    联动菜单id
 * @param $id           生成联动菜单的样式id
 * @param $defaultvalue 默认值
 */
function menu_linkage($linkageid = 0, $id = 'linkid', $defaultvalue = 0, $is_create_html = false) {
	$linkages = D('Linkage')->where(['keyid' => $linkageid])->order('listorder asc')->field('id, name, parentid')->select();
	$tree     = list_to_tree($linkages, 'id', 'parentid');
	$tree     = (defined('HTML_CREATE') && HTML_CREATE) ? str_replace('\\u', '\\\\u', json_encode($tree)) : json_encode($tree);
	$html     = "";
	if (!defined('LINKAGE_INIT_1')) {
		define('LINKAGE_INIT_1', 1);
		$html .= '<script type="text/javascript" src="' . asset('js/linkage/linkagesel.js') . '"></script>' . "\n";
	}
	$html .= $defaultvalue ? '<input type="hidden" name="info[' . $id . ']" value="' . $defaultvalue . '" id="' . $id . '-' . $linkageid . '">' : '<input type="hidden" name="info[' . $id . ']" value="" id="' . $id . '-' . $linkageid . '">';
	$html .= "\n";
	$html .= '<select class="tp-admin-select-' . $id . '" id="' . $id . '" width="100"></select>' . "\n";
	$html .= '<script type="text/javascript">
    $(function(){
            var opts = {
                data: ' . $tree . ',
                selStyle: "margin-left: 3px;",
                select:  "#' . $id . '",
                dataReader: {id: "id", name: "name", cell: "_child"},
                defVal: [' . str_replace('-', ',', $defaultvalue) . '],
                head: false
            };
            var linkageSel_' . $linkageid . ' = new LinkageSel(opts);
            linkageSel_' . $linkageid . '.onChange(function(){
                var input = $("#' . $id . '-' . $linkageid . '")
                ids = this.getSelectedDataArr("id");
                input.val(ids.join("-"));
            });
    });
    </script>';

	return $html;
}
function is_valid_domain_name($domain_name) {
	return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name) //valid chars check
		 && preg_match("/^.{1,253}$/", $domain_name) //overall length check
		 && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name)); //length of each label
}